package org.sao.auth.config;

import javax.sql.DataSource;

import org.sao.auth.compoent.SaoWebResponseExceptionTranslator;
import org.sao.common.constant.SecurityConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;



/**
 * @author lengleng
 * @date 2017/10/27
 * 认证服务器逻辑实现
 */

@Configuration
@Order(Integer.MIN_VALUE)
@EnableAuthorizationServer
public class SaoAuthorizationConfig extends AuthorizationServerConfigurerAdapter {
	
	    @Autowired
	    private AuthServerConfig authServerConfig;
	
	    @Autowired
	    private AuthenticationManager authenticationManager;

	    @Autowired
	    private DataSource dataSource;
	    
	    @Autowired
	    private RedisConnectionFactory redisConnectionFactory;
	    
	    @Autowired
	    private UserDetailsService userDetailsService;
	    
	    @Autowired
	    private SaoWebResponseExceptionTranslator saoWebResponseExceptionTranslator;

	    
	    @Bean
	    public PasswordEncoder passwordEncoder() {
	        return new BCryptPasswordEncoder();
	    }
	    
	    
	    /*
	     * 
	     * ClientDetailsServiceConfigurer：用来配置客户端详情服务（ClientDetailsService），
	     * 客户端详情信息在这里进行初始化，你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息。
	     * (non-Javadoc)
	     * @see org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter#configure(org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer)
	     */
	    @Override
	    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
	    	 clients.inMemory()
             .withClient(authServerConfig.getClientId())
             .secret(authServerConfig.getClientSecret())
             .authorizedGrantTypes(SecurityConstants.REFRESH_TOKEN, SecurityConstants.PASSWORD,SecurityConstants.AUTHORIZATION_CODE)
             .scopes(authServerConfig.getScope());
        }
	    
	    /*
	     * AuthorizationServerEndpointsConfigurer：用来配置授权（authorization）以及令牌（token）的访问端点和令牌服务(token services)。
	     * (non-Javadoc)
	     * @see org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter#configure(org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer)
	     */
	    @Override
	    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
	        endpoints
	                .tokenStore(new RedisTokenStore(redisConnectionFactory))
	                .authenticationManager(authenticationManager)
	                .exceptionTranslator(saoWebResponseExceptionTranslator)
	                .reuseRefreshTokens(false)
	                .userDetailsService(userDetailsService);
	    }
	    
	    
	    /*
	     * AuthorizationServerSecurityConfigurer：用来配置令牌端点(Token Endpoint)的安全约束.
	     * (non-Javadoc)
	     * @see org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter#configure(org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer)
	     */
	    @Override
	    public void configure(AuthorizationServerSecurityConfigurer security)
	            throws Exception {
	        security.allowFormAuthenticationForClients();
	        //.tokenKeyAccess("isAuthenticated()")
            //.checkTokenAccess("permitAll()");// 支持form表单验证
	    }
	    
	    
}